module MC.AudioModel {
	export class SourceNode {
		public constructor(AudioBuffer: AudioBuffer, context: AudioContext) {
			this.AudioBuffer = AudioBuffer;
			this.context = context;
		}
		public context: AudioContext;
		public AudioBufferSourceNode: AudioBufferSourceNode = null;
		public AudioBuffer: AudioBuffer;
		/** 播放时的时间 */
		private beginTime: number = null;
		public start(yanchi: number = 0, currentTime: number = null, time: number = null) {
			if (this.AudioBufferSourceNode) {
				this.AudioBufferSourceNode.stop();
				this.AudioBufferSourceNode = null;
			}
			this.AudioBufferSourceNode = this.context.createBufferSource();
			this.AudioBufferSourceNode.buffer = this.AudioBuffer;

			this.AudioBufferSourceNode.connect(this.context.destination);

			this.beginTime = yanchi + this.context.currentTime;

			if (currentTime === null && time === null) {
				this.AudioBufferSourceNode.start(yanchi);
			} else if (time === null) {
				this.beginTime = yanchi + this.context.currentTime - currentTime;
				this.AudioBufferSourceNode.start(yanchi, currentTime);
			} else {
				this.AudioBufferSourceNode.start(yanchi, currentTime, time);
			}
			this.analyser = null;
			this.bindgainNodeContext();

		}
		/** 播放音乐 */
		public play() {
			if (this.pauseTime >= this.duration) {
				this.pauseTime = 0;
			}
			this.start(0, this.pauseTime);
			this.pauseTime = 0;
			this.loop = this._loop;
		}
		/** 暂停 */
		public pause() {
			this.pauseTime = this.currentTime;
			//debug.log("this.pauseTime = this.currentTime;");
			if (this.AudioBufferSourceNode) {
				//	debug.log("this.AudioBufferSourceNode.stop();");
				this.AudioBufferSourceNode.stop();
				this.AudioBufferSourceNode = null;
			}
		}
		/** 停止音乐 */
		public close() {
			this.pauseTime = 0;
			if (this.AudioBufferSourceNode) {
				//	debug.log("this.AudioBufferSourceNode.stop();");
				this.AudioBufferSourceNode.stop();
				this.AudioBufferSourceNode = null;
			}
		}
		/** 获取音乐的总时间 */
		get duration() {
			return this.AudioBuffer.duration;
		}
		private _loop = false;
		/** 暂停时,记录暂停的时间 */
		private pauseTime: number = 0;
		get loop() {
			return this.AudioBufferSourceNode.loop;
		}
		set loop(is: boolean) {
			this._loop = is;
			this.AudioBufferSourceNode.loop = is;
		}
		/** 返回正在播放的时间 */
		get currentTime(): number {

			if (this.beginTime === null) {
				//	debug.log("currentTime()NULL" + this.beginTime);
				return 0;
			}
			if (this.pauseTime == 0) {
				let current = this.context.currentTime - this.beginTime;
				if (current > this.duration) {	///如果播放的时间超过了总时间,并且是loop的,返回取模
					if (this.loop) {
						let cur = (current * 100) % (this.duration * 100) / 100
						if (cur === 0) {
							cur += 0.01;
						}
						///debug.log("currentTime()cur:"+cur );
						return cur;
					} else {
						this.pauseTime = 0;
						///	debug.log("currentTime()return 0;" );
						return 0;
					}
				} else {
					return current;
				}

			} else {
				return this.pauseTime;
			}
		}
		/** 标记是否被按钮控制暂停的对象 */
		public isButtionStop = false;

		/** 判断是否正在使用
		 * 如果是播放结束,或者没有播放,返回false,否则返回true
		 */
		get isRuntime() {
			let currentTime = this.currentTime;
			if (currentTime > 0 && currentTime < this.duration) {
				return true;
			} else {
				return false;
			}
		}

		private gainNode: GainNode = null;
		/** 绑定上下文 */
		private bindgainNodeContext() {
			this.gainNode = this.context.createGain();
			this.AudioBufferSourceNode.connect(this.gainNode);
			this.gainNode.connect(this.context.destination);
			this.volume=this._volume;	
		}
		private _volume=1;
		/** 设置音量 */
		set volume(v: number) {
			if (this.gainNode) {
				this.gainNode.gain.value = v;
			}
			this._volume=v;
		}
		get volume() {
			return this.gainNode.gain.value;
		}

		private analyser: AnalyserNode = null;
		/**
		 * 获取频谱数组
		 */
		public getAnalyser() {
			if (!this.analyser) {
				this.analyser = this.context.createAnalyser();
				this.analyser.fftSize = 128 * 2;
				this.AudioBufferSourceNode.connect(this.analyser);
			}
			var dataArray = new Uint8Array(this.analyser.frequencyBinCount);
			this.analyser.getByteTimeDomainData(dataArray);
			return dataArray;
		}
	}
}